import os
import sys

import requests
from loguru import logger

from mdtool.entity.fs_entity import FsSheet, FsTable
from mdtool.feishu_robot import FsRobot

ARTICLES_SHEET_NAME = "test"
ARTICLES_MEDIA_ID_COLUMN = "A:A"


class FsError:
    code: int = 0
    msg: str = ""

    def __init__(self, fs_json):

        self.code = fs_json["code"]
        self.msg = fs_json["msg"]


class FsClient:

    def __init__(self):
        self.config = {}
        self.config["APP_ID"] = os.getenv("FEISHU_APP_ID")
        self.config["APP_SECRET"] = os.getenv("FEISHU_APP_SECRET")
        self.robot = FsRobot()

    # 获取访问令牌
    def get_access_token(self):
        return self.robot._get_tenant_access_token()

    # 向飞书表格写入数据
    def write_data_to_sheet(self, spreadsheet_token, sheet_id, data_range, values):
        return self.robot.write_data_to_sheet(
            spreadsheet_token, sheet_id, data_range, values
        )

    def _add_sheet(self, spreadsheet_token, sheet_title: str = "Sheet1", index=1):

        ret = self.robot.add_sheet(spreadsheet_token, "Sheet1", index=1)
        if ret["code"] != 0:
            return FsError(ret)
        reply = ret["data"]["replies"][0]
        return FsSheet.fromJson(reply["addSheet"]["properties"])

    def delete_spreadsheet(self, title):
        ret = self.robot.delete_spreadsheet(title)
        if ret["code"] != 0:
            logger.warning(f"无法创建飞书表格：{title}")
            return FsError(ret)
        return FsSheet.fromJson(ret["data"]["spreadsheet"])

    def create_spreadsheet(self, title):
        ret = self.robot.create_spreadsheet(title)
        if ret["code"] != 0:
            return FsError(ret)
        return FsSheet.fromJson(ret["data"]["spreadsheet"])

    # 获取指定电子表格的所有工作表信息
    def get_sheet_info(self, spreadsheet_token):
        url = f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{self.get_access_token()}/sheets/query"
        headers = {
            "Authorization": f"Bearer {self.get_access_token()}",
            "Content-Type": "application/json; charset=utf-8",
        }
        response = requests.get(url, headers=headers)
        return response.json()

    def get_all_files_under_folder_token(self, folder_token):
        ret = self.robot.get_all_files_under_folder_token(folder_token)
        if ret["code"] == 0:
            return ret["data"]["files"]
        else:
            return FsError(ret)

    def get_root_folder_token(self):
        result = self.robot.get_root_folder_token()
        token = result["data"]["token"]
        if token:
            return token
        return FsError(result)

    def find_document_by_file_title(self, title):
        return self.__find_file_by_attr("name", title)

    def find_document_by_file_token(self, token):
        return self.__find_file_by_attr("token", token)

    def __find_file_by_attr(self, attr, value):
        files = self.get_all_files_under_folder_token(self.get_root_folder_token())
        for file in files:
            ret = file[attr]
            if ret == value:
                return file
        return None

    def get_sheet_ids_by_file_token(self, file_token, sheet_index=0):
        file = self.find_document_by_file_token(file_token)
        file_token = file["token"]
        url = f"https://open.feishu.cn/open-apis/sheets/v3/spreadsheets/{file_token}/sheets/query"
        headers = {
            "Authorization": f"Bearer {self.get_access_token()}",
            "Content-Type": "application/json; charset=utf-8",
        }
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            ret = response.json()
            if ret["code"] == 0:
                return ret["data"]["sheets"][sheet_index]["sheet_id"]
            else:
                return ""

    def upload_wx_article_published(
        self, sheet_name: str, range: str, data: list
    ) -> bool:
        spreadsheet = self.find_document_by_file_title(sheet_name)
        spreadsheet_token = spreadsheet["token"]
        logger.debug("spreadsheet_token: {}", spreadsheet_token)
        sheet_id = self.get_sheet_ids_by_file_token(spreadsheet_token)
        if sheet_id == "":
            logger.warning("")
            return False
        res = self.write_data_to_sheet(spreadsheet_token, sheet_id, range, data)
        return res["code"] == 0

    def read_data_from_sheet(self, spreadsheet_token, sheet_id, data_range):
        """
        读取飞书表格指定 sheet_id 和 range 的所有数据。
        :param spreadsheet_token: 表格 token
        :param sheet_id: 工作表 id
        :param data_range: 读取范围（如 'A1' 或 'A1:B10'）
        :return: 读取到的数据（二维数组）
        """
        url = f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{spreadsheet_token}/values/{sheet_id}!{data_range}"
        headers = {
            "Authorization": f"Bearer {self.get_access_token()}",
            "Content-Type": "application/json; charset=utf-8",
        }
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            result = response.json()
            if result.get("code") == 0:
                return result["data"].get("valueRange", {}).get("values", [])
            else:
                logger.error(f"读取飞书表格数据失败: {result}")
                return []
        else:
            logger.error(f"HTTP请求失败，状态码: {response.status_code}")
            return []

    def get_spreadsheet_token_and_sheet_id_by_name(self, spreadsheet_name, sheet_name):
        """
        根据 spreadsheet 名称和 sheet 名称，返回 spreadsheet 的 token 和 sheet_id。
        :param spreadsheet_name: 表格名称
        :param sheet_name: 工作表名称
        :return: (spreadsheet_token, sheet_id) 或 (None, None) 如果未找到
        """
        spreadsheet = self.find_document_by_file_title(spreadsheet_name)
        if not spreadsheet:
            logger.error(f"未找到名为 {spreadsheet_name} 的 spreadsheet")
            return None, None
        spreadsheet_token = spreadsheet["token"]
        url = f"https://open.feishu.cn/open-apis/sheets/v3/spreadsheets/{spreadsheet_token}/sheets/query"
        headers = {
            "Authorization": f"Bearer {self.get_access_token()}",
            "Content-Type": "application/json; charset=utf-8",
        }
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            result = response.json()
            if result.get("code") == 0:
                for sheet in result["data"]["sheets"]:
                    if sheet["title"] == sheet_name:
                        return spreadsheet_token, sheet["sheet_id"]
                logger.error(f"未找到名为 {sheet_name} 的 sheet")
                return spreadsheet_token, None
            else:
                logger.error(f"获取 sheet 列表失败: {result}")
                return spreadsheet_token, None
        else:
            logger.error(f"HTTP请求失败，状态码: {response.status_code}")
            return spreadsheet_token, None

    def read_article_ids(self):
        spreadsheet = self.find_document_by_file_title(ARTICLES_SHEET_NAME)
        spreadsheet_token = spreadsheet["token"]
        logger.debug("spreadsheet_token: {}", spreadsheet_token)
        sheet_id = self.get_sheet_ids_by_file_token(spreadsheet_token)
        result = self.read_data_from_sheet(
            spreadsheet_token, sheet_id, ARTICLES_MEDIA_ID_COLUMN
        )
        # 返回一维 id 集合
        return {row[0] for row in result if row}

    def find_line_num_by_prefix(self, prefix: str):
        spreadsheet = self.find_document_by_file_title(ARTICLES_SHEET_NAME)
        spreadsheet_token = spreadsheet["token"]
        logger.debug("spreadsheet_token: {}", spreadsheet_token)
        sheet_id = self.get_sheet_ids_by_file_token(spreadsheet_token)
        if not spreadsheet:
            logger.error(f"未找到名为 {ARTICLES_SHEET_NAME} 的 spreadsheet")
            return []
        spreadsheet_token = spreadsheet["token"]
        sheet_ids = self.get_sheet_ids_by_file_token(spreadsheet_token)
        if isinstance(sheet_ids, list):
            if not sheet_ids:
                logger.error("未找到任何 sheet_id")
                return []
            sheet_id = sheet_ids[0]
        else:
            sheet_id = sheet_ids
        # 读取第一列所有数据
        data = self.read_data_from_sheet(spreadsheet_token, sheet_id, "A:A")
        # 找到以 prefix 开头的所有 row_id（飞书行号从1开始）
        row_ids = []
        for idx, row in enumerate(data, start=1):
            if row and str(row[0]).startswith(prefix):
                row_ids.append(idx)
                print(idx)
        return spreadsheet_token, sheet_id, row_ids

    def delete_by_prefix(self, prefix: str):
        spreadsheet_token, sheet_id, row_nums = self.find_line_num_by_prefix(prefix)
        result = self.robot.delete_rows(spreadsheet_token, sheet_id, row_nums)
        if len(result) != 0:
            print("以下行数在删除时出错了：\n\t " + ",".format())


if __name__ == "__main__":
    file_name = "公众号 CD20 文章发布列表"
    sheet_name = "已发布文章列表"
    client = FsClient()
    table = client.create_spreadsheet(file_name)
    if table == FsTable.EMPTY:
        print("创建 表格 失败")
        sys.exit(1)
    ret = client._add_sheet(table.spreadsheet_token, sheet_name)
    if ret == FsSheet.EMPTY:
        print("增加 Sheet 失败")
        sys.exit(1)
